import difflib
import librosa
import numpy as np

def extract_features(audio_path):
    """提取音频特征（如音高、强度、语速等）并评估发音质量"""
    y, sr = librosa.load(audio_path, sr=None)
    
    # 提取音高（Pitch）
    pitch, voiced_flag, voiced_probs = librosa.pyin(y, fmin=librosa.note_to_hz('C2'), fmax=librosa.note_to_hz('C7'))
    
    # 音量强度
    intensity = np.abs(y).mean()
    
    # 语速（每分钟音节数）
    syllables = len(librosa.effects.split(y, top_db=20))  # 简单估算音节数量
    speech_rate = syllables / (len(y) / sr / 60)
    
    return pitch, intensity, speech_rate

def compare_texts(user_text, reference_text):
    """对比用户文本和参考文本并提供详细反馈"""
    user_words = user_text.split()
    reference_words = reference_text.split()
    
    # 使用SequenceMatcher计算文本相似度
    seq_matcher = difflib.SequenceMatcher(None, user_words, reference_words)
    
    differences = []
    for tag, i1, i2, j1, j2 in seq_matcher.get_opcodes():
        if tag != 'equal':  # 找到不同的部分
            differences.append((tag, user_words[i1:i2], reference_words[j1:j2]))
    
    return differences

def generate_positive_feedback(overall_score):
    """根据评分给出不同层次的正向反馈"""
    if overall_score >= 90:
        return ["发音非常标准，继续保持！"]
    elif overall_score >= 80:
        return ["发音接近标准，继续努力保持。"]
    elif overall_score >= 70:
        return ["发音良好，但仍有提升空间。"]
    elif overall_score >= 60:
        return ["发音有进步空间，继续练习。"]
    else:
        return ["需要更多练习来改善发音。"]

def evaluate_pronunciation(user_text, reference_text, audio_path):
    differences = compare_texts(user_text, reference_text)
    pitch, intensity, speech_rate = extract_features(audio_path)
    
    # 计算文本匹配得分
    seq_matcher = difflib.SequenceMatcher(None, user_text, reference_text)
    text_match_score = seq_matcher.ratio() * 100
    
    # 初始化音频得分
    audio_score = 100
    pitch_score = 100
    intensity_score = 100
    speech_rate_score = 100
    
    # 根据音高调整评分
    if pitch.mean() < 100 or pitch.mean() > 300:  # 音高过低或过高
        pitch_score -= 10
        audio_score -= 10
    # 根据音量强度调整评分
    if intensity < 0.01:  # 音量过低
        intensity_score -= 10
        audio_score -= 10
    # 根据语速调整评分
    if speech_rate < 100:  # 语速过慢
        speech_rate_score -= 10
        audio_score -= 10
    elif speech_rate > 200:  # 语速过快
        speech_rate_score -= 10
        audio_score -= 10
    
    # 综合评分
    overall_score = 0.6 * text_match_score + 0.4 * audio_score
    
    # 根据文本差异生成反馈
    feedback = []
    for tag, user_words, ref_words in differences:
        if tag == 'replace':  # 用户发音错误的词
            for user_word, ref_word in zip(user_words, ref_words):
                feedback.append(f"单词‘{user_word}’发音不准确，应为‘{ref_word}’。")
        elif tag == 'delete':  # 用户遗漏的词
            for word in ref_words:
                feedback.append(f"缺少了单词‘{word}’。")
        elif tag == 'insert':  # 用户多出的词
            for word in user_words:
                feedback.append(f"额外添加了单词‘{word}’。")
    
    # 添加音频方面的反馈
    if pitch.mean() < 100:
        feedback.append("音高偏低，请提高音调。")
    elif pitch.mean() > 300:
        feedback.append("音高偏高，请降低音调。")
    if intensity < 0.01:
        feedback.append("音量较低，请加大声音。")
    if speech_rate < 100:
        feedback.append("语速较慢，请适当加快速度。")
    elif speech_rate > 200:
        feedback.append("语速较快，请放慢语速。")

    # 生成正向反馈
    positive_feedback = generate_positive_feedback(overall_score)
    feedback.extend(positive_feedback)
    
    return {
        'feedback': feedback,
        'score': round(overall_score, 2),  # 保留两位小数
        'text_match_score': round(text_match_score, 2),
        'pitch_score': round(pitch_score, 2),
        'intensity_score': round(intensity_score, 2),
        'speech_rate_score': round(speech_rate_score, 2)
    }
